program UserInterface;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  SampleCommon,
  DIrr in '..\..\DSource\DIrr.pas',
  DIrr.GUI in '..\..\DSource\DIrr.GUI.pas',
  DIrr.Color in '..\..\DSource\DIrr.Color.pas',
  DIrr.Rect in '..\..\DSource\DIrr.Rect.pas',
  DIrr.Event in '..\..\DSource\DIrr.Event.pas',
  DIrr.Vector2D in '..\..\DSource\DIrr.Vector2D.pas',
  DIrr.Vector3D in '..\..\DSource\DIrr.Vector3D.pas',
  DIrr.Video in '..\..\DSource\DIrr.Video.pas',
  DIrr.Base in '..\..\DSource\DIrr.Base.pas',
  DIrr.Types in '..\..\DSource\DIrr.Types.pas',
  DIrr.Scene in '..\..\DSource\DIrr.Scene.pas',
  DIrr.Structs in '..\..\DSource\DIrr.Structs.pas',
  DIrr.Aabbox3D in '..\..\DSource\DIrr.Aabbox3D.pas',
  DIrr.Matrix4 in '..\..\DSource\DIrr.Matrix4.pas',
  DIrr.Texture in '..\..\DSource\DIrr.Texture.pas',
  DIrr.Collections in '..\..\DSource\DIrr.Collections.pas',
  DIrr.Consts in '..\..\DSource\DIrr.Consts.pas';

type
  // Declare a structure to hold some context for the event receiver so that it
  // has it available inside its OnEvent() method.
  SAppContext = record
    Device: TIrrlichtDevice;
    Counter: S32;
    ListBox: TGUIListBox;
  end;

  // Define some values that we'll use to identify individual GUI controls.
const
    GUI_ID_BASE                       = 100;
    GUI_ID_QUIT_BUTTON                = GUI_ID_BASE + 1;
    GUI_ID_NEW_WINDOW_BUTTON          = GUI_ID_BASE + 2;
    GUI_ID_FILE_OPEN_BUTTON           = GUI_ID_BASE + 3;
    GUI_ID_TRANSPARENCY_SCROLL_BAR    = GUI_ID_BASE + 4;


type
  TMyEventReceiver = class(TEventReceiver)
  private
    FContext: SAppContext;
  public
    constructor Create(const AContext: SAppContext);
  public
    function OnEvent(const Event: SEvent): Boolean; override; stdcall;
  end;

(*
Set the skin transparency by changing the alpha values of all skin-colors
*)
procedure SetSkinTransparency(Alpha: S32; ASkin: TGUISkin);
var
  i: EGUI_DEFAULT_COLOR;
  Col: TIrrColor;
begin
  for i := Low(EGUI_DEFAULT_COLOR) to High(EGUI_DEFAULT_COLOR) do
  begin
    Col := ASkin.GetColor(i)^;
    Col.SAlpha := Alpha;
    ASkin.SetColor(i, Col);
  end;
end;

var
  DriverType: E_DRIVER_TYPE;
  Device: TIrrlichtDevice;
  Driver: TVideoDriver;
  Env: TGUIEnvironment;
  Skin: TGUISkin;
  Font: TGUIFont;
  ScrollBar: TGUIScrollBar;
  ListBox: TGUIListBox;
  Context: SAppContext;
  Receiver: TMyEventReceiver;
  Clr: TIrrColor;

{ TMyEventReceiver }

constructor TMyEventReceiver.Create(const AContext: SAppContext);
begin
  FContext := AContext;
end;

function TMyEventReceiver.OnEvent(const Event: SEvent): Boolean;
var
  id, apos, val: S32;
  Env: TGUIEnvironment;
  Dialog: TGUIFileOpenDialog;
  Window: TGUIWindow;
begin
  Result := False;

  if Event.EventType = EET_GUI_EVENT then
  begin
    id := Event.GUIEvent.Caller.GetID;
    Env := Context.Device.GetGUIEnvironment;

    case Event.GUIEvent.EventType of
			(*
			If a scrollbar changed its scroll position, and it is
			'our' scrollbar (the one with id GUI_ID_TRANSPARENCY_SCROLL_BAR), then we change
			the transparency of all gui elements. This is a very
			easy task: There is a skin object, in which all color
			settings are stored. We simply go through all colors
			stored in the skin and change their alpha value.
			*)
      EGET_SCROLL_BAR_CHANGED:
      begin
        if id = GUI_ID_TRANSPARENCY_SCROLL_BAR then
        begin
          apos := TGUIScrollBar(Event.GUIEvent.Caller).GetPos;
          SetSkinTransparency(apos, Env.GetSkin);
        end;
      end;

			(*
			If a button was clicked, it could be one of 'our'
			three buttons. If it is the first, we shut down the engine.
			If it is the second, we create a little window with some
			text on it. We also add a string to the list box to log
			what happened. And if it is the third button, we create
			a file open dialog, and add also this as string to the list box.
			That's all for the event receiver.
			*)
      EGET_BUTTON_CLICKED:
      begin
        case id of
          GUI_ID_QUIT_BUTTON:
          begin
            Context.Device.CloseDevice;
            Result := True;
          end;

          GUI_ID_NEW_WINDOW_BUTTON:
          begin
            Context.ListBox.AddItem('Window created');
            Context.Counter := Context.Counter + 1;
            if Context.Counter > 200 then
              Context.Counter := 0;
            val := Context.Counter;

            Window := Env.AddWindow
                      (
                        TIrrRect.Create(100 + val, 100 + val, 300 + val, 200 + val),
                        False,
                        'Text window'
                      );

            Env.AddStaticText('Please close me',[35, 35, 140, 50],
              True, False, Window);

            Result := True;
          end;

          GUI_ID_FILE_OPEN_BUTTON:
          begin
            Context.ListBox.AddItem('File open');
            // There are some options for the file open dialog
            // We set the title, make it a modal window, and make sure
            // that the working directory is restored after the dialog
            // is finished.
            Env.AddFileOpenDialog('Please choose a file', True, nil, -1, True);
            Result := True;
          end;
        end;
      end;

      EGET_FILE_SELECTED:
      begin
        // show the model filename, selected in the file dialog
        Dialog := TGUIFileOpenDialog(Event.GUIEvent.Caller);
        Context.ListBox.AddItem(Dialog.GetFileName);
      end;
    end;
  end;
end;

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
    DriverType := DriverChoiceConsole;
    if DriverType = EDT_COUNT then
    begin
      ExitCode := 1;
      Exit;
    end;

    // create device and exit if creation failed
    Device := createDevice(DriverType, [640, 480], 16);
    if Device = nil then
    begin
      ExitCode := 1;   // could not create selected driver.
      Exit;
    end;

    (* The creation was successful, now we set the event receiver and
      store pointers to the driver and to the gui environment. *)

    Device.SetWindowCaption('Irrlicht Engine - User Interface Demo');
    Device.SetResizable(true);

	  Driver := Device.GetVideoDriver;
	  Env := Device.GetGUIEnvironment;

    (*
    To make the font a little bit nicer, we load an external font
    and set it as the new default font in the skin.
    To keep the standard font for tool tip text, we set it to
    the built-in font.
    *)


    Skin := Env.GetSkin;
    Font := Env.GetFont('..\..\media\fonthaettenschweiler.bmp');
    Clr.Color32 := $FFFFFFFF;
    if Assigned(Font) then
      Skin.SetFont(Font);
    Skin.SetFont(Env.GetBuiltInFont, EGDF_TOOLTIP);

    (*
    We add three buttons. The first one closes the engine. The second
    creates a window and the third opens a file open dialog. The third
    parameter is the id of the button, with which we can easily identify
    the button in the event receiver.
    *)

    Env.AddButton([10, 240, 110, 240 + 32], nil, Ord(GUI_ID_QUIT_BUTTON),
      'Quit', 'Exits Program');
    Env.AddButton([10, 280, 110, 280 + 32], nil, Ord(GUI_ID_NEW_WINDOW_BUTTON),
      'New Window', 'Launches a new Window');
    Env.AddButton([10, 320, 110, 320 + 32], nil, Ord(GUI_ID_FILE_OPEN_BUTTON),
      'File Open', 'Opens a file');

    (*
    Now, we add a static text and a scrollbar, which modifies the
    transparency of all gui elements. We set the maximum value of
    the scrollbar to 255, because that's the maximal value for
    a color value.
    Then we create an other static text and a list box.
    *)


    Env.AddStaticText('Transparent Control:', [150, 20, 350, 40], True);
    Scrollbar := Env.AddScrollBar(True, TIrrRect.Create(150, 45, 350, 60),
      nil, Ord(GUI_ID_TRANSPARENCY_SCROLL_BAR));
    Scrollbar.SetMax(255);
    Scrollbar.SetPos(255);

    SetSkinTransparency(Scrollbar.GetPos, Env.GetSkin);


    // set Scrollbar position to alpha value of an arbitrary element
    Clr := Env.GetSkin.GetColor(EGDC_WINDOW)^;
    Scrollbar.SetPos(Clr.SAlpha);

    Env.AddStaticText('Logging ListBox:', [50, 110, 250, 130], True);
    Listbox := Env.AddListBox(IrrRect(50, 140, 250, 210));
    Env.AddEditBox('Editable Text', IrrRect(350, 80, 550, 100));

    // Store the appropriate data in a Context structure.
    Context.Device := Device;
    Context.Counter := 0;
    Context.Listbox := Listbox;

    // Then create the event Receiver, giving it that Context structure.
    Receiver := TMyEventReceiver.Create(Context);

    // And tell the Device to use our custom event Receiver.
    Device.SetEventReceiver(Receiver);

    (*
    And at last, we create a nice Irrlicht Engine logo in the top left corner.
    *)
    Env.AddImage(Driver.GetTexture('..\..\media\irrlichtlogo2.png'), Vector2D(10, 10));

    (*
    That's all, we only have to draw everything.
    *)

    while (Device.Run and Assigned(Driver)) do
    begin
      if Device.IsWindowActive then
      begin
        Driver.BeginScene(True, True, IrrColor(200, 200, 200, 255));

        Env.DrawAll;

        Driver.EndScene;
      end;
    end;

    Device.Drop;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
